//
//  DNDataBase.m
//  DanoneEA
//
//  Created by 3ti_Jery on 16/10/19.
//  Copyright © 2016年 翔傲科技. All rights reserved.
//

#import "DNDataBase.h"
#import "FMDatabase.h"
#import "AppDelegate.h"
#import "DNCryingDao.h"
#import "DNStoolDao.h"
#import "DNFeedingDao.h"
#import "DNUserManager.h"

@interface DNDataBase ()

@property (nonatomic, retain) FMDatabaseQueue *dbQueue;

@end

static NSString *const DBNAME = @"danone.sqlite";

@implementation DNDataBase

static DNDataBase *_instance = nil;

+ (instancetype)shareInstance
{
    static dispatch_once_t onceToken ;
    dispatch_once(&onceToken, ^{
        _instance = [[super allocWithZone:NULL] init];
    });
    
    return _instance;
}

- (FMDatabaseQueue *)createDatabaseQueue
{
    if (_dbQueue == nil) {
        NSString* docsdir = [NSSearchPathForDirectoriesInDomains( NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
        NSFileManager *fileManager = [NSFileManager defaultManager];
        BOOL isDir;
        BOOL exit =[fileManager fileExistsAtPath:docsdir isDirectory:&isDir];
        if (!exit || !isDir) {
            [fileManager createDirectoryAtPath:docsdir withIntermediateDirectories:YES attributes:nil error:nil];
        }
        NSString* dbpath = [docsdir stringByAppendingPathComponent:DBNAME];
        _dbQueue = [[FMDatabaseQueue alloc] initWithPath:dbpath];
    }
    return _dbQueue;
}

- (FMDatabase *)createDatabaseIfNeeded
{
    //取用户目录
    FMDatabase *db = [FMDatabase databaseWithPath:[self dbPath]];
    //DDLogError(@"Is SQLite compiled with it's thread safe options turned on? %@!", [FMDatabase isThreadSafe] ? @"Yes" : @"No");
    
    if (![db open]) {
        DDLogError(@"Could not open db.");
        return nil;
    }
    else
        [db setKey:DB_SECRETKEY];
    
    [db setShouldCacheStatements:YES];
    
    if ([db hadError]) {
        DDLogError(@"Err %d: %@", [db lastErrorCode], [db lastErrorMessage]);
    }
    return db;
}

- (NSString *)dbPath {
    
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documents = [paths objectAtIndex:0];
    NSString *database_path = [documents stringByAppendingPathComponent:DBNAME];
    
    DDLogInfo(@"database_path: %@", database_path);
    return database_path;
}

//初始化数据库表
- (void)initDBTable{
    
    DNDataBase * dnDB =  [DNDataBase shareInstance];
    [dnDB.dbQueue inDatabase:^(FMDatabase *db) {
        
        DDLogVerbose(@"init db start ....");
        
        [db setKey:DB_SECRETKEY];
        
        [db executeUpdate:[NSString stringWithFormat:@"DROP TABLE IF EXISTS %@;",Crying_TABLE]];
        [db executeUpdate:[NSString stringWithFormat:@"DROP TABLE IF EXISTS %@;",Stool_TABLE]];
        [db executeUpdate:[NSString stringWithFormat:@"DROP TABLE IF EXISTS %@;",Feeding_TABLE]];
        [db executeUpdate:[NSString stringWithFormat:@"DROP TABLE IF EXISTS %@;",TimeConsume_TABLE]];
        [db executeUpdate:[NSString stringWithFormat:@"DROP TABLE IF EXISTS %@;",Notification_TABLE]];
        
        [db executeUpdate:[DNCryingDao getCreateSQL]];
        [db executeUpdate:[DNStoolDao getCreateSQL]];
        [db executeUpdate:[DNFeedingDao getCreateSQL]];
        [db executeUpdate:[self getCreateTimeConsumeTableSQL]];
        [db executeUpdate:[self getCreateNotificationTableSQL]];
        
        DDLogVerbose(@"init db end ");
    }];
    
//    [self initTimeConsumeTable];
}


- (void)clearAllTableData
{
    
    DNDataBase * dnDB =  [DNDataBase shareInstance];
    [dnDB.dbQueue inDatabase:^(FMDatabase *db) {
        
        DDLogVerbose(@"clear all table data start ....");
        if(![db open])
        {
            DDLogError(@"clearAllTableData error: %@", db.lastErrorMessage);
            return;
        }
        else
            [db setKey:DB_SECRETKEY];
        
        BOOL ret = [db executeUpdate:[NSString stringWithFormat:@"DELETE FROM %@ ;",Crying_TABLE]];
        ret =[db executeUpdate:[NSString stringWithFormat:@"DELETE FROM %@ ;",Stool_TABLE]];
        ret =[db executeUpdate:[NSString stringWithFormat:@"DELETE FROM %@ ;",Feeding_TABLE]];
        ret =[db executeUpdate:[NSString stringWithFormat:@"DELETE FROM %@ ;",Notification_TABLE]];
        
        DDLogVerbose(@"clear all table data end ");
    }];
    
}

- (void)clearDataWithTableName:(NSString *) tableName
{
    DNDataBase *dnDB =  [DNDataBase shareInstance];
    [dnDB.dbQueue inDatabase:^(FMDatabase *db) {
        if(![db open])
        {
            DDLogError(@"clearDataWithTableName error: %@", db.lastErrorMessage);
            return;
        }
        else
            [db setKey:DB_SECRETKEY];
        
        [db executeUpdate:[NSString stringWithFormat:@"DELETE FROM %@ ;",tableName]];
        
        [db close];
    }];
}


- (NSString *)getQueryAllModelSqlWithTableName:(NSString *) tableName andBeforeDays:(int)days{
    
    NSString *currentStamp = [self getTimeStampWithDate:[NSDate date]];
    NSString *startStamp = [self getOneDayZeroTimeStampWithBeforeDays:days];
    
    //FIXME: error status by sql
    return [NSString
            stringWithFormat:@"SELECT * FROM %@ WHERE '%@' < %@ AND '%@' > %@ AND %@ != %@ ORDER BY createTime ASC;",tableName,startStamp,DairyBase_CreateTime,currentStamp,DairyBase_CreateTime,DairyBase_Status,[NSNumber numberWithInt:OPStatus_NORMAL]
            ];
}

- (NSString *)getTimeStampWithDate:(NSDate *)date
{
    NSString *stampStr = [NSString stringWithFormat:@"%.0f", [date timeIntervalSince1970]];
    return stampStr;
}

- (NSString *)getQueryAppDisplayModelSqlWithTableName:(NSString *)tableName
{
    NSString *synchronousDays = [[DNUserManager sharedInstance] getValueFromDefaultWithKey:UserDefaultKey_SynchronousDays];
    NSString *startStamp = [self getOneDayZeroTimeStampWithBeforeDays:synchronousDays.intValue];
    
    // Senela Add:2016-11-03; 修复创建时间差导致最新几条数据查询丢失的问题
    return [NSString
            stringWithFormat:@"SELECT * FROM %@ WHERE '%@' < %@ ;",tableName,startStamp,DairyBase_CreateTime
            ];
}


-(NSString *)getOneDayZeroTimeStampWithBeforeDays:(int)days
{
    NSCalendar *calendar = [NSCalendar currentCalendar];
    
    NSCalendarUnit unit = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay | NSCalendarUnitHour|NSCalendarUnitMinute|NSCalendarUnitSecond;
    
    NSDateComponents *component = [calendar components:unit fromDate:[NSDate date]];
    component.day-=days;
    component.hour = 0;
    component.minute = 0;
    component.second = 0;
    
    NSDate *dateFromDateComponentsForDate = [calendar dateFromComponents:component];
    
    NSString * timeStamp = [self getTimeStampWithDate:dateFromDateComponentsForDate];
    
    return timeStamp;
}

- (NSString *)convertToJsonStringWithObject:(id)value
{
    if(value == [NSNull null]){
        return @"";
    }else if( [value isKindOfClass:[NSMutableArray class]]){
        value = (NSMutableArray *)value;
    }else if ([value isKindOfClass:[NSMutableDictionary class]]){
        value = (NSMutableDictionary *)value;
    }
    NSError *err = nil;
    NSData *jsonData = [NSJSONSerialization dataWithJSONObject:value options:NSJSONWritingPrettyPrinted error:&err];
    NSString *jsonStr = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
    
    return jsonStr;
}


- (NSMutableArray *)getAllObjectModelNotSynchronized
{
    return nil;
}

- (NSMutableArray *)getAppDisplayObjectModel
{
    return nil;
}


// Senela Add:2016-11-2;
#pragma mark - Private methods  for time consume module
-(void)initTimeConsumeTable
{
    DNDataBase * dnDB =  [DNDataBase shareInstance];
    [dnDB.dbQueue inDatabase:^(FMDatabase *db) {
        
        if(![db open])
        {
            DDLogError(@"initTimeConsumeTable error:%@", db.lastErrorMessage);
            return;
        }
        else
            [db setKey:DB_SECRETKEY];
        
        BOOL ret = [db executeUpdate:[NSString stringWithFormat:@"DROP TABLE IF EXISTS %@;",TimeConsume_TABLE]];
        if(!ret)
        {
            DDLogError(@"DROP %@ TABLE error:%@",TimeConsume_TABLE, db.lastErrorMessage);
            return;
        }
        ret = [db executeUpdate:[self getCreateTimeConsumeTableSQL]];
        if(!ret)
        {
            DDLogError(@"CREATE %@ TABLE error:%@",TimeConsume_TABLE, db.lastErrorMessage);
            return;
        }
        
    }];
    
}

-(NSString *)getCreateTimeConsumeTableSQL
{
    return [NSString
            stringWithFormat:@"CREATE TABLE IF NOT EXISTS %@ (%@ text primary key not null,%@ text,%@ text,%@ text,%@ text);",
            TimeConsume_TABLE,
            TimeConsume_Date,
            TimeConsume_Stool,
            TimeConsume_Feeding,
            TimeConsume_Crying,
            TimeConsume_APP
            ];
}

#pragma mark - Private methods for Notification module
-(NSString *)getCreateNotificationTableSQL
{
    return [NSString
            stringWithFormat:@"CREATE TABLE IF NOT EXISTS %@ (%@ text primary key not null,%@ text,%@ text,%@ text,%@ text,%@ text,%@ text,%@ text,%@ text);",
            Notification_TABLE,
            DairyBase_ServerId,
            Notification_Type,
            Notification_Mode,
            Notification_time,
            Notification_diaryreg_Id,
            DairyBase_ModifyReason,
            DairyBase_DeleteReason,
            DairyBase_CreateTime,
            DairyBase_ModifyTime
            ];
}

@end
